package br.usp.ime.dojo.server;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import br.usp.ime.dojo.client.DojoException;
import br.usp.ime.dojo.client.DojoRoomDTO;
import br.usp.ime.dojo.client.DojoRoomService;
import br.usp.ime.dojo.client.UserDTO;
import br.usp.ime.dojo.core.entities.DojoRoom;
import br.usp.ime.dojo.core.entities.User;
import br.usp.ime.dojo.core.exceptions.DuplicatedRoomException;
import br.usp.ime.dojo.core.exceptions.StartSessionException;
import br.usp.ime.dojo.core.exceptions.UserAlreadyInTheRoomException;
import br.usp.ime.dojo.core.exceptions.UserNotInTheRoomException;
import br.usp.ime.dojo.core.repositories.DojoRoomRepository;
import br.usp.ime.dojo.core.repositories.RepositoryFactory;
import br.usp.ime.dojo.core.repositories.UserRepository;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

@SuppressWarnings("serial")
public class DojoRoomServiceImpl extends RemoteServiceServlet implements DojoRoomService {
	
	private DojoRoom dojoRoom;
	String codeText;
	String testCodeText;
	String resultCodeText;

	public List<String> getUserListFromRoom(String dojoRoomName){
		DojoRoomRepository dojoRepository = RepositoryFactory.createDojoRoomRepository();
		DojoRoom dojoRoom = dojoRepository.get(dojoRoomName);
		List<String> r = new ArrayList<String>();
		
		for(User user : dojoRoom.getUsers()){
			r.add(user.getName());
		}
		return r;
	}

	public List<String> getPilotQueueFromRoom(String dojoRoomName) {
		DojoRoomRepository dojoRoomRepository = RepositoryFactory.createDojoRoomRepository();
		DojoRoom dojoRoom = dojoRoomRepository.get(dojoRoomName);
		List<String> r = new ArrayList<String>();
		
		Queue<User> q = new LinkedList<User> (dojoRoom.getPilots());
		
		while(!q.isEmpty()){
			r.add(q.poll().getName());
		}
		return r;
	}
	public String getPilot(String dojoRoomName){
		if(RepositoryFactory.createDojoRoomRepository().get(dojoRoomName).getPilot() != null)
			return RepositoryFactory.createDojoRoomRepository().get(dojoRoomName).getPilot().getName(); 
		return "none";
		
	}
	public String getCopilot(String dojoRoomName){
		if(RepositoryFactory.createDojoRoomRepository().get(dojoRoomName).getCopilot() != null){
			return RepositoryFactory.createDojoRoomRepository().get(dojoRoomName).getCopilot().getName();
		}
		return "none";
	}

	public void exitDojoRoom(String userName, String dojoRoomName) {
		DojoRoom dojoRoom = RepositoryFactory.createDojoRoomRepository().get(dojoRoomName);
		User user = RepositoryFactory.createUserRepository().get(userName);
		
		try {
			dojoRoom.removeUser(user);
		} catch (UserNotInTheRoomException e) {
			e.printStackTrace();
		}
	}
	
	public DojoRoomDTO createDojoRoom(String name, String description, String creator, List<String> selectedLanguages) throws DojoException {
		try {
			DojoRoomRepository dojoRoomRepository = RepositoryFactory.createDojoRoomRepository();
			UserRepository userRepository = RepositoryFactory.createUserRepository();
			DojoRoom room = new DojoRoom(name, description, userRepository.get(creator), selectedLanguages);
			dojoRoomRepository.addRoom(room);
			return Convert.fromDojoRoom(room);
		} catch (DuplicatedRoomException e) {
			throw new DojoException(e.getMessage());
		}
	}
	
	public void cleanAll() {
		DojoRoomRepository dojoRoomRepository = RepositoryFactory.createDojoRoomRepository();
		dojoRoomRepository.clearAll();
	}
	
	public void join(DojoRoomDTO dojoRoomDTO, UserDTO user) throws DojoException {
		try {
			DojoRoomRepository repository = RepositoryFactory.createDojoRoomRepository();
			DojoRoom dojoRoom = repository.get(dojoRoomDTO.getName());
			dojoRoom.addUser(Convert.toUser(user));
		} catch (UserAlreadyInTheRoomException e) {
			throw new DojoException(e.getMessage());
		}
	}
	
	public ArrayList<DojoRoomDTO> getDojoRoomList() throws DojoException {
//		RoomListingSvc roomListingService = new RoomListingSvc();
		
		try {
			ArrayList<DojoRoom> dojoRoomList = RepositoryFactory.createDojoRoomRepository().getDojoRoomList();
			ArrayList<DojoRoomDTO> dojoRoomDTOList = new ArrayList<DojoRoomDTO>();
			for( DojoRoom it : dojoRoomList){
				dojoRoomDTOList.add( Convert.fromDojoRoom(it));
			}
			return dojoRoomDTOList;
			
		} catch (Exception e) {
			throw new DojoException(e.getMessage());
		}
	}
	
	public void toggle(DojoRoomDTO dojoRoomDTO, UserDTO userDTO){
		DojoRoomRepository repository = RepositoryFactory.createDojoRoomRepository();
		
		DojoRoom dojoRoom = repository.get(dojoRoomDTO.getName());
		
		if (dojoRoom.pilotQueueHasUser(Convert.toUser(userDTO))) {
			dojoRoom.removeFromPilotQueue(Convert.toUser(userDTO));
		}
		else {
			dojoRoom.addToPilotQueue(Convert.toUser(userDTO));
		}
	}
	

	public void setRoomDescription(String newDescription, String roomName) {
		dojoRoom = RepositoryFactory.createDojoRoomRepository().get(roomName);
		dojoRoom.setDescription(newDescription);
  
		/*try {
			dojoRoom.sessionStart();
			codeText = "";
			return true;
		} catch (InsufficientUsersInPilotQueueException e) {
			// TODO Auto-generated catch block
			//e.printStackTrace();
			return false;
		}*/
	}

	public String getRoomDescription(String roomName) {
		dojoRoom = RepositoryFactory.createDojoRoomRepository().get(roomName);
		return dojoRoom.getDescription();
	}

	public boolean verifyIfIsStarted(String roomName) {
		dojoRoom = RepositoryFactory.createDojoRoomRepository().get(roomName);
		return dojoRoom.sessionHasStarted();
	}
	
	public void updateCodeInServer(String codeText) {
		this.codeText = codeText;
	}
	
	public void updateTestCodeInServer(String testCodeText) {
		this.testCodeText = testCodeText;
	}
	
	public String updateCodeInClient() {
		return codeText;
	}
	
	public String updateTestCodeInClient() {
		return testCodeText;
	}
	
	public List<String> getAvailableLanguages() {
		List<String> languages = new ArrayList<String>();
		languages.add("Ruby");
		languages.add("Java");
		return languages;
	}
	
	public List<String> getInitialLanguages(String roomName) {
		dojoRoom = RepositoryFactory.createDojoRoomRepository().get(roomName);
		return dojoRoom.getInitialLanguages();
	}
	
	public List<String> getSelectedLanguages(String roomName) {
		dojoRoom = RepositoryFactory.createDojoRoomRepository().get(roomName);
		return dojoRoom.getSelectedLanguages();
	}

	public void setSelectedLanguages(String name, String language) {
		dojoRoom = RepositoryFactory.createDojoRoomRepository().get(name);
		dojoRoom.toggleLanguageSelection(language);
	}

	public void startSession(String roomName) throws DojoException {
		dojoRoom = RepositoryFactory.createDojoRoomRepository().get(roomName);
		try {
			dojoRoom.sessionStart();
		} catch (StartSessionException e) {
			throw new DojoException(e.getMessage());
		}
	}

	public void updateResultCodeInServer(String s) {
		resultCodeText = s; 
	}
	
	public String updateResultCodeInClient() {
		return resultCodeText; 
	}
}

